﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace Gmantis.Controls.Toolbar
{
    public enum ToolbarControlSize
    {
        Large,
        Medium,
        Small
    }

    [ContentProperty("ControlSizes")]
    public class ToolbarGroupSizeDefinition
    {
        // Methods
        public ToolbarGroupSizeDefinition()
        {
            this.ControlSizes = new Collection<ToolbarControlSize>();
        }

        // Properties
        public Collection<ToolbarControlSize> ControlSizes { get; set; }
    }

    [TemplatePart(Name = "NormalGrid", Type = typeof(Grid)), 
    TemplatePart(Name = "DialogLauncherCollapsed", Type = typeof(Button)), 
    TemplatePart(Name = "Collapsed", Type = typeof(Grid)), 
    TemplatePart(Name = "CollapsedGrid", Type = typeof(Grid)), 
    TemplatePart(Name = "Items", Type = typeof(ItemsPresenter)), 
    TemplatePart(Name = "DropDown", Type = typeof(DropDownButton)), 
    TemplatePart(Name = "DialogLauncher", Type = typeof(Button)), 
    TemplatePart(Name = "Normal", Type = typeof(Grid))]
    public class ToolbarGroup : System.Windows.Controls.ItemsControl
    {
        // Fields
        internal Grid _elementCollapsed;
        internal Grid _elementCollapsedGrid;
        internal Button _elementDialogLauncher;
        internal Button _elementDialogLauncherCollapsed;
        internal DropDownButton _elementDropDown;
        internal ItemsPresenter _elementItems;
        internal Grid _elementNormal;
        internal Grid _elementNormalGrid;
        internal bool _isLoaded;
        internal const string CollapsedElementName = "Collapsed";
        internal const string CollapsedGridElementName = "CollapsedGrid";
        internal const string DialogLauncherCollapsedElementName = "DialogLauncherCollapsed";
        internal const string DialogLauncherElementName = "DialogLauncher";
        internal const string DropDownElementName = "DropDown";
        public static readonly DependencyProperty FocusBrushProperty = DependencyProperty.Register("FocusBrush", typeof(Brush), typeof(ToolbarGroup), null);
        public static readonly DependencyProperty GroupSizeDefinitionsProperty = DependencyProperty.Register("GroupSizeDefinitions", typeof(Collection<ToolbarGroupSizeDefinition>), typeof(ToolbarGroup), new PropertyMetadata(null));
        public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register("Header", typeof(object), typeof(ToolbarGroup), new PropertyMetadata(null));
        private bool invalidate;
        internal const string ItemsElementName = "Items";
        public static readonly DependencyProperty ItemTemplateSelectorProperty = DependencyProperty.Register("ItemTemplateSelector", typeof(DataTemplateSelector), typeof(ToolbarGroup), new PropertyMetadata(null));
        public static readonly DependencyProperty MouseOverBrushProperty = DependencyProperty.Register("MouseOverBrush", typeof(Brush), typeof(ToolbarGroup), null);
        internal const string NormalElementName = "Normal";
        internal const string NormalGridElementName = "NormalGrid";
        public static readonly DependencyProperty PressedBrushProperty = DependencyProperty.Register("PressedBrush", typeof(Brush), typeof(ToolbarGroup), null);
        public static readonly DependencyProperty ShowDialogLauncherProperty = DependencyProperty.Register("ShowDialogLauncher", typeof(bool), typeof(ToolbarGroup), new PropertyMetadata(false, new PropertyChangedCallback(ToolbarGroup.OnShowDialogLauncherChanged)));

        // Events
        public event EventHandler DialogLauncherClick;

        // Methods
        public ToolbarGroup()
        {
            base.DefaultStyleKey = typeof(ToolbarGroup);
            this.SetCustomDefaultValues();
        }

        private void btn_Click(object sender, RoutedEventArgs e)
        {
            if (this._elementDropDown.IsDropDownOpen)
            {
                this._elementDropDown.IsDropDownOpen = false;
            }
        }

        private void ToolbarGroup_Loaded(object sender, RoutedEventArgs e)
        {
            if (this.invalidate)
            {
                this.invalidate = false;
                base.InvalidateMeasure();
            }
        }

        private T GetTemplateChild<T>(string childName, bool required, ref string errors) where T : class
        {
            DependencyObject templateChild = base.GetTemplateChild(childName);
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "template part", childName, templateChild, required, ref errors);
            return (templateChild as T);
        }

        private static Storyboard GetTemplateChildResource(FrameworkElement root, string resourceName, bool required, ref string errors)
        {
            return GetTemplateChildResource<Storyboard>(root, resourceName, required, ref errors);
        }

        private static T GetTemplateChildResource<T>(FrameworkElement root, string resourceName, bool required, ref string errors) where T : class
        {
            object child = root.Resources[resourceName];
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "resource", resourceName, child, required, ref errors);
            return (child as T);
        }

        private void InitializeDialogLauncherCollapsedPart()
        {
            this._elementDialogLauncherCollapsed.Click += delegate(object s, RoutedEventArgs e)
            {
                if (this.DialogLauncherClick != null)
                {
                    this.DialogLauncherClick(this, EventArgs.Empty);
                }
            };
            this._elementDialogLauncherCollapsed.Visibility = this.ShowDialogLauncher ? Visibility.Visible : Visibility.Collapsed;
        }

        private void InitializeDialogLauncherPart()
        {
            this._elementDialogLauncher.Click += delegate(object s, RoutedEventArgs e)
            {
                if (this.DialogLauncherClick != null)
                {
                    this.DialogLauncherClick(this, EventArgs.Empty);
                }
            };
            this._elementDialogLauncher.Visibility = this.ShowDialogLauncher ? Visibility.Visible : Visibility.Collapsed;
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            this._elementDropDown.IsDropDownOpen = false;
            if (this._elementCollapsedGrid.Children.Contains(this._elementItems))
            {
                this._elementCollapsedGrid.Children.Remove(this._elementItems);
            }
            if (!this._elementNormalGrid.Children.Contains(this._elementItems))
            {
                this._elementNormalGrid.Children.Add(this._elementItems);
            }
            this._elementCollapsed.Visibility = Visibility.Collapsed;
            this._elementNormal.Visibility = Visibility.Visible;
            Size size = base.MeasureOverride(availableSize);
            if (size.Width >= availableSize.Width)
            {
                this._elementNormalGrid.Children.Remove(this._elementItems);
                this._elementCollapsedGrid.Children.Add(this._elementItems);
                this._elementCollapsed.Visibility = Visibility.Visible;
                this._elementNormal.Visibility = Visibility.Collapsed;
                size = base.MeasureOverride(availableSize);
            }
            return size;
        }

        private void OnAfterApplyTemplate()
        {
            if (base.ReadLocalValue(FrameworkElement.StyleProperty) == DependencyProperty.UnsetValue)
            {
                Toolbar toolbar = this.FindParent<Toolbar>();
                if ((toolbar != null) && (toolbar.ToolbarGroupStyle != null))
                {
                    base.Style = toolbar.ToolbarGroupStyle;
                    this.invalidate = true;
                }
            }
        }

        public override void OnApplyTemplate()
        {
            string errors = string.Empty;
            base.OnApplyTemplate();
            this._isLoaded = true;
            this._elementNormal = this.GetTemplateChild<Grid>("Normal", true, ref errors);
            this._elementNormalGrid = this.GetTemplateChild<Grid>("NormalGrid", true, ref errors);
            this._elementCollapsed = this.GetTemplateChild<Grid>("Collapsed", true, ref errors);
            this._elementCollapsedGrid = this.GetTemplateChild<Grid>("CollapsedGrid", true, ref errors);
            this._elementItems = this.GetTemplateChild<ItemsPresenter>("Items", true, ref errors);
            this._elementDropDown = this.GetTemplateChild<DropDownButton>("DropDown", true, ref errors);
            this._elementDialogLauncher = this.GetTemplateChild<Button>("DialogLauncher", true, ref errors);
            if (this._elementDialogLauncher != null)
            {
                this.InitializeDialogLauncherPart();
            }
            this._elementDialogLauncherCollapsed = this.GetTemplateChild<Button>("DialogLauncherCollapsed", true, ref errors);
            if (this._elementDialogLauncherCollapsed != null)
            {
                this.InitializeDialogLauncherCollapsedPart();
            }
            if (!string.IsNullOrEmpty(errors))
            {
                this._isLoaded = false;
                if ((base.Template != null) && !PlatformIndependent.IsInDesignMode(this))
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Template cannot be applied to ToolbarGroup.\nDetails: {0}", new object[] { errors }));
                }
            }
            else
            {
                this.OnAfterApplyTemplate();
            }
        }

        protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
        {
            base.OnItemsChanged(e);
            if (e.NewItems != null)
            {
                foreach (object obj2 in e.NewItems)
                {
                    ButtonBase base2 = obj2 as ButtonBase;
                    if (base2 != null)
                    {
                        base2.Click += new RoutedEventHandler(this.btn_Click);
                    }
                }
            }
            if (e.OldItems != null)
            {
                foreach (object obj3 in e.OldItems)
                {
                    ButtonBase base3 = obj3 as ButtonBase;
                    if (base3 != null)
                    {
                        base3.Click -= new RoutedEventHandler(this.btn_Click);
                    }
                }
            }
        }

        private static void OnShowDialogLauncherChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            ToolbarGroup group = (ToolbarGroup)obj;
            if (group._elementDialogLauncher != null)
            {
                group._elementDialogLauncher.Visibility = group.ShowDialogLauncher ? Visibility.Visible : Visibility.Collapsed;
            }
            if (group._elementDialogLauncherCollapsed != null)
            {
                group._elementDialogLauncherCollapsed.Visibility = group.ShowDialogLauncher ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            base.PrepareContainerForItemOverride(element, item);
            if (this.ItemTemplateSelector != null)
            {
                ContentPresenter presenter = element as ContentPresenter;
                if (presenter != null)
                {
                    presenter.ContentTemplate = this.ItemTemplateSelector.SelectTemplate(item, element);
                }
            }
            ToolbarStrip target = element as ToolbarStrip;
            if (target != null)
            {
                target.Background = new SolidColorBrush(Colors.Transparent);
                target.SetBinding<ToolbarGroup>(ToolbarStrip.ButtonBackgroundProperty, this, tg => tg.Background);
                target.SetBinding<ToolbarGroup>(ToolbarStrip.ButtonForegroundProperty, this, tg => tg.Foreground);
                target.SetBinding<ToolbarGroup>(Control.BorderBrushProperty, this, tg => tg.BorderBrush);
                target.SetBinding<ToolbarGroup>(ToolbarStrip.MouseOverBrushProperty, this, tg => tg.MouseOverBrush);
                target.SetBinding<ToolbarGroup>(ToolbarStrip.PressedBrushProperty, this, tg => tg.PressedBrush);
                target.SetBinding<ToolbarGroup>(ToolbarStrip.FocusBrushProperty, this, tg => tg.FocusBrush);
            }
            ToolbarButton button = element as ToolbarButton;
            if (button != null)
            {
                button.Background = new SolidColorBrush(Colors.Transparent);
                button.SetBinding<ToolbarGroup>(ToolbarButton.MouseOverBrushProperty, this, tg => tg.MouseOverBrush);
                button.SetBinding<ToolbarGroup>(ToolbarButton.PressedBrushProperty, this, tg => tg.PressedBrush);
            }
            ToolbarToggleButton button2 = element as ToolbarToggleButton;
            if (button2 != null)
            {
                button2.Background = new SolidColorBrush(Colors.Transparent);
                button2.SetBinding<ToolbarGroup>(ToolbarToggleButton.MouseOverBrushProperty, this, tg => tg.MouseOverBrush);
                button2.SetBinding<ToolbarGroup>(ToolbarToggleButton.PressedBrushProperty, this, tg => tg.PressedBrush);
            }
            ToolbarDropDown down = element as ToolbarDropDown;
            if (down != null)
            {
                down.Background = new SolidColorBrush(Colors.Transparent);
                down.SetBinding<ToolbarGroup>(ToolbarDropDown.ContentBackgroundProperty, this, tg => tg.Background);
                down.SetBinding<ToolbarGroup>(ToolbarDropDown.MouseOverBrushProperty, this, tg => tg.MouseOverBrush);
                down.SetBinding<ToolbarGroup>(ToolbarDropDown.PressedBrushProperty, this, tg => tg.PressedBrush);
            }
        }

        private void SetCustomDefaultValues()
        {
            this.GroupSizeDefinitions = new Collection<ToolbarGroupSizeDefinition>();
            base.Loaded += new RoutedEventHandler(this.ToolbarGroup_Loaded);
        }

        // Properties
        public Brush FocusBrush
        {
            get { return (Brush)GetValue(FocusBrushProperty); }
            set { SetValue(FocusBrushProperty, value); }
        }

        public Collection<ToolbarGroupSizeDefinition> GroupSizeDefinitions
        {
            get { return (Collection<ToolbarGroupSizeDefinition>)GetValue(GroupSizeDefinitionsProperty); }
            set { SetValue(GroupSizeDefinitionsProperty, value); }
        }

        public object Header
        {
            get { return GetValue(HeaderProperty); }
            set { SetValue(HeaderProperty, value); }
        }

        public DataTemplateSelector ItemTemplateSelector
        {
            get { return (DataTemplateSelector)GetValue(ItemTemplateSelectorProperty); }
            set { SetValue(ItemTemplateSelectorProperty, value); }
        }

        public Brush MouseOverBrush
        {
            get { return (Brush)GetValue(MouseOverBrushProperty); }
            set { SetValue(MouseOverBrushProperty, value); }
        }

        public Brush PressedBrush
        {
            get { return (Brush)GetValue(PressedBrushProperty); }
            set { SetValue(PressedBrushProperty, value); }
        }

        public bool ShowDialogLauncher
        {
            get { return (bool)GetValue(ShowDialogLauncherProperty); }
            set { SetValue(ShowDialogLauncherProperty, value); }
        }
    }

    public class ToolbarGroupCollection : System.Collections.ObjectModel.ObservableCollection<ToolbarGroup>
    {
        // Methods
        internal ToolbarGroupCollection()
        {
        }
    }
}
